package cn.jiedanba.itext5.util;

import cn.jiedanba.itext5.BCProvider;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Collection;

public class PkiUtil extends BCProvider {

    /**
     * 私钥签名
     *
     * @param pk   私钥
     * @param alg  签名算法
     * @param data 待签名数据
     * @return
     */
    public static byte[] sign(PrivateKey pk, String alg, byte[] data) {
        try {
            Signature sig = Signature.getInstance(alg, BC);
            sig.initSign(pk);
            sig.update(data);
            return sig.sign();
        } catch (Exception e) {
            throw new RuntimeException("私钥签名异常", e);
        }
    }

    /**
     * 获取公钥
     *
     * @param key
     * @return
     * @throws Exception
     */
    public static PublicKey getPublicKey(byte[] encodedKey) {
        try {
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
            KeyFactory keyFactory = KeyFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME);
            PublicKey publicKey = keyFactory.generatePublic(keySpec);
            return publicKey;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取私钥
     *
     * @param encodedKey encoded according to the PKCS #8 standard
     * @return
     */
    public static PrivateKey getPrivateKey(byte[] encodedKey) {
        PrivateKey privateKey = null;
        try {
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
            KeyFactory keyFactory;
            keyFactory = KeyFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME);
            privateKey = keyFactory.generatePrivate(keySpec);
            return privateKey;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

    }

    /**
     * 读取X.509证书
     *
     * @param crtPath 证书路径
     * @return
     * @throws CertificateException
     * @throws IOException
     * @throws NoSuchProviderException
     */
    public static X509Certificate readX509Certificate(byte[] cer)
            throws CertificateException, IOException, NoSuchProviderException {
        CertificateFactory cf = CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME);
        X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(cer));
        return cert;
    }

    /**
     * 获取公钥证书链
     *
     * @param cer
     * @return
     */
    public static Certificate[] getCertificateChain(byte[] cer) {
        try {
            CertificateFactory certificatefactory = CertificateFactory.getInstance("X.509",
                    BouncyCastleProvider.PROVIDER_NAME);
            // 获取crt证书的证书链
            Collection<Certificate> chainList = new ArrayList<Certificate>(
                    certificatefactory.generateCertificates(new ByteArrayInputStream(cer)));
            return chainList.toArray(new Certificate[]{});
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("获取证书链出错", e);
        }
    }

}
